package com.zhiqiang.gameserver.netty;

import com.zhiqiang.gameserver.entity.ZQGameServerEntity;
import com.zhiqiang.gameserver.queue.CommonQueue;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.ReferenceCountUtil;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;



/**
 * @author YAO
 */
public class NettyGameServerHandler extends ChannelInboundHandlerAdapter {
    // 心跳丢失计数器
    private int counter;

    private static Logger log= LogManager.getLogger(NettyGameServerHandler.class.getName());

    /**
     * 进入连接
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        Channel incoming = ctx.channel();
        System.out.println("来自" + incoming.remoteAddress() + "客户端上线！");
        log.info("来自" + incoming.remoteAddress() + "客户端上线");


    }
    /**
     * 断开连接
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        Channel incoming = ctx.channel();
        System.out.println("来自" + incoming.remoteAddress() + "客户端下线");
        log.info("来自" + incoming.remoteAddress() + "客户端下线");
    }

    /**
     * 读消息
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.err.println("receive message:\n"+msg.toString());
        log.info("接收到来自"+ctx.channel().remoteAddress()+"的客户端的请求信息");
        if(null==msg){
            return;
        }
        ZQGameServerEntity zq = (ZQGameServerEntity) msg;
        if(0x00000002 == zq.getMsgType()){
            handleHeartbreat(zq.getData());
        }else {
            Channel channel = ctx.channel();
            zq.setChannel(channel);
            /**
             * TODO 数据多可以多分队列
             */
            CommonQueue.getInstance().put(zq);


        }

    }

    private void handleHeartbreat(byte[] data) {
        // 将心跳丢失计数器置为0
        counter = 0;
        System.out.println("收到心跳包");
        ReferenceCountUtil.release(data);
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
         log.info("message read complete!");
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent) {
            // 空闲31s之后触发 (心跳包丢失)
            if (counter >= 3) {
                // 连续丢失3个心跳包 (断开连接)
                ctx.channel().close().sync();
                System.out.println(ctx.channel().remoteAddress()+"客户端已与服务器断开连接");
                log.info(ctx.channel().remoteAddress()+"客户端已与服务器断开连接");
            } else {
                counter++;
                System.out.println("与"+ctx.channel().remoteAddress()+"客户端丢失了第 " + counter + " 个心跳包");
            }
        }
    }
}
